#-*- coding: utf-8 -*-

# subversion info:
# $HeadURL: http://htpc-utils.googlecode.com/svn/trunk/HtpcUtils/SubDaemon.py $
# $Author: SkAsI.7 $
# $Id: SubDaemon.py 23 2010-12-01 12:01:45Z SkAsI.7 $
# $Revision: 23 $

"""
Subtitle daemon module. Provides automatic subtitle download and management.
"""

# Imports externals
import os
import logging
import datetime
# import tempfile
import subprocess

# Imports internals
import Database


class SubDaemon(object):
  """
  SubDaemon class. Provides operations to automatically download subtitles.
  """

  def __init__(self, eventManager):
    object.__init__(self)
    self.__log = logging.getLogger('sub-daemon')
    self.__eventManager = eventManager

  def cron(self):
    """
    (Cron)ological run. Analize pending subtitles and process them.
    """
    for subtitle in Database.Subtitle.select():
      # Error downloading
      if self._download(subtitle.videoFile, subtitle.subLanguage):
        if subtitle.tries:
          subtitle.tries -= 1
          if subtitle.tries == 0:
            subtitle.destroySelf()
            continue
        if subtitle.dueDate:
          if datetime.datetime.now() > subtitle.dueDate:
            subtitle.destroySelf()
            continue
      # Successfully download
      else:
        subtitle.destroySelf()

  def add(self, videoFile, subLanguage, dueDate=None, tries=None):
    """
    Add a new video file to the subtitle queue.

    :param videoFile: Path to the video file. Must be complete before adding
      it.
    :type videoFile: str

    :param subLanguage: Subtitle language to download. "en_EN" or "en" formats
      supported.
    :type subLanguage: str

    :param dueDate: Time to stop looking for a subtitle. Defaults to never.
    :type dueDate: L{datetime.datetime} object or None (never)

    :param tries: Number of tries to download subtitle. Defaults to infinity.
    :type tries: int or None (infinity)

    :raises: RuntimeError if something go bad.
    """
    videoFile = os.path.abspath(videoFile)
    if not os.path.exists(videoFile):
      raise RuntimeError, 'video file "%s" doesn\'t exist' % videoFile
    if len(subLanguage) > 5:
      raise RuntimeError, 'invalid subtitle language, must be like ' \
          '"en_EN" or "en"'
    if not dueDate is None and not isinstance(dueDate, datetime.datetime):
      raise RuntimeError, 'invalid due date, must be an instance of ' \
          'datetime.datetime or None'
    if not tries is None and not isinstance(tries, int):
      raise RuntimeError, 'invalid tries number, must be a number or None'
    Database.Subtitle(videoFile=videoFile, subLanguage=subLanguage,
        dueDate=dueDate, tries=tries)

  def delete(self, videoFile):
    """
    Delete a video file from the subtitle queue.

    :param videoFile: Path to the video file. Must be complete before adding
      it.
    :type videoFile: str

    :raises: RuntimeError if something go bad.
    """
    videoFile = os.path.abspath(videoFile)
    try:
      subtitle = Database.Subtitle.select(
          Database.Subtitle.q.videoFile == videoFile)[-1]
    except IndexError:
      raise RuntimeError, 'video file "%s" not registered on the DB' % \
          videoFile
    else:
      subtitle.destroySelf()

  def pendingList(self):
    """
    Returns the list of pending subtitles to download.

    :returns: the list of pending subtitles.
    :rtype: str list
    """
    pending = []
    for subtitle in Database.Subtitle.select():
      pending.append("""
Video filename: %s
Subtitle language: %s
Added datetime: %s
Due datetime: %s
Tries: %s""" % (
          subtitle.videoFile, subtitle.subLanguage,
          subtitle.addedDate.strftime('%d/%m/%y %H:%M:%S'),
          (subtitle.dueDate is not None) and
            subtitle.dueDate.strftime('%d/%m/%y %H:%M:%S') or 'Never',
          (subtitle.tries is not None) and subtitle.tries or 'Infinity')
      )
    return pending

  def _download(self, video, language):
    """
    Perform the download of a subtitle for the given video in the given
      language.

    :param video: Video filename which subtitle download.
    :type video: str

    :param language: Language code in "en_EN" or "en" formats.
    :type language: str

    :returns: 0 on success or 3 on failure
    :rtype: int
    """
    # Check video file existance # 
    if not os.access(video, os.R_OK):
      self.delete(video)
      return 3

    # Run subdownloader -c -l $language -v $video #
    params = ['subdownloader'
        , '-c'
        , '-l', language
        , '-V', video
        , '--rename-subs']
    self.__log.debug('Running "%s"' % ' '.join(params))
    retCode = subprocess.call(params)
    self.__log.debug('subdownloader returned %d on exit' % retCode)
    if retCode:
      return 3
    
    # If success (return code?) rename and move back subtitles file #
    subtitle = os.path.splitext(video)[0] + '.srt'
    self.__log.debug('Subtitle file will be "%s"' % subtitle)
    subtitle = os.path.split(subtitle)[1]
    for file in os.listdir(os.path.split(video)[0]):
      if file == subtitle:
        break # Found!
    else:
      self.__log.debug('No subtitle file was found')
      return 3

    self.__eventManager.add('Subtitle found',
      'The (%s) subtitle for %s was saved' % (
        language, video))

    return 0

